<template>
	<div id="container" class="flex h-full">
		<div class="flex flex-col h-full flex-1 p-2">
			<div>
				<el-text tag="b">事件：</el-text>
				<el-select v-model="data.eventSelected" placeholder="选择事件" size="large" style="width: 240px"><el-option
						v-for="item in eventOptions" :key="item.value" :label="item.label" :value="item.value" />
				</el-select>
			</div>
			<div class="mt-4">
				<el-text tag="b">事件名称(eventName):</el-text>
				<el-select class="ml-4" v-model="data.eventSelected" placeholder="事件名称" size="large"
					style="width: 240px"><el-option v-for="item in eventOptions" :key="item.value" :label="item.label"
						:value="item.value" />
				</el-select>
			</div>
			<div>
				<el-text tag="b">事件数据(data):</el-text>
				<el-tooltip class="box-item" placement="right">
					<template #content><text class="text-lg">支持占位符，发送报文将自动填充设备信息，如{"cgid": "${cgid}"}<br />可用的占位符：
							<br />
							产品名称：${productName}<br />
							商家id：${merchantId}<br />
							商家名称：${merchantName}<br />
							门店id：${storeId}<br />
							门店名称：${storeName}<br />
							ProductKey：${pk}<br />
							DeviceName：${dn}<br />
							DeviceSecret：${ds}<br />
							cgid：${cgid}<br />
							设备别名：${deviceAlias}<br />
							毫秒时间戳：${millisecond}<br />
						</text></template>
					<el-icon class="ml-2">
						<QuestionFilled />
					</el-icon>
				</el-tooltip>
			</div>
			<div id="code-div" class="flex-1 mt-4">
				<div class="flex flex-row">
					<div class="code-content">
						<Codemirror v-model:value="data.eventBody" :options="cmOptions" border
							:height="codemirrorHeight" ref="cmRef" class="w-full">
						</Codemirror>
					</div>
				</div>
			</div>
			<div class="mt-4">
				<el-button class="ml-2" @click="compress">压缩</el-button>
				<el-button class="ml-2" @click="formatJson">格式化</el-button>
				<el-button class="ml-2" @click="saveJson">保存</el-button>
				<el-button type="primary"
					@click="$emit('reportEvent', data.eventSelected, data.eventBody)">发送指令</el-button>
			</div>
		</div>
		<!-- 报文存档列表 -->
		<div class="flex flex-col border px-2 w-80 h-full">
			<div class="flex flex-row p-2 h-12">
				<el-text tag="b" class="flex-1">报文存档</el-text>
				<el-button @click="newEventBody">新增</el-button>
				<el-popconfirm title="确认清空?" @confirm="clearStoredBody">
					<template #reference>
						<el-button>清空</el-button>
					</template>
				</el-popconfirm>
			</div>
			<div class="slide-body-container">
				<div class="flex-1 h-full overflow-y-auto slide-body-content">
					<div v-if="data.storedEventBodyList && data.storedEventBodyList.length > 0">
						<div v-for="item in data.storedEventBodyList"
							class="flex p-2 border border-slate-100 duration-300">
							<div class="flex-1 hover:text-blue-400 truncate"
								:class="{'text-blue-400': item.id == data.selectedBodyId }"
								@click="selectEventBody(item)">
								<el-tooltip effect="light" :content="item.name" placement="left-start">{{item.name}}
								</el-tooltip>
							</div>
							<div class="flex text-right">
								<el-button-group class="ml-4">
									<!-- <el-button :icon="Edit" /> -->
									<el-popconfirm title="确认删除?" @confirm="delEventBody(item.id)">
										<template #reference>
											<el-button :icon="Delete" />
										</template>
									</el-popconfirm>
								</el-button-group>
							</div>
						</div>
					</div>
					<div v-else><el-empty description="无数据" :image-size="100" /></div>
				</div>
			</div>
		</div>
	</div>
</template>

<script setup>
import { ref, reactive, onMounted } from 'vue'
import Codemirror from "codemirror-editor-vue3";
import jsonlint from "jsonlint-mod";
// language json or js
import "codemirror/mode/javascript/javascript.js";
import "codemirror/addon/lint/lint.css";
import "codemirror/addon/lint/lint.js";
import "codemirror/addon/lint/json-lint";
import { ElMessage,ElMessageBox } from 'element-plus'
import { debounce } from '@/utils/common'
import {QuestionFilled, Edit, Delete,CirclePlus} from '@element-plus/icons-vue'
import {getRandomString} from '@/utils/random'

defineEmits(['reportEvent'])

const defaultBody = '{"productName":"${productName}","merchantId":"${merchantId}","merchantName":"${merchantName}", "storeName":"${storeName}", "storeId":"${storeId}", "cgid": "${cgid}", "pk":"${pk}", "dn":"${dn}", "ds":"${ds}", "deviceAlias":"${deviceAlias}"}'
const data = reactive({
  eventSelected: 'deviceParamUpdate',
  //事件报文
  eventBody: defaultBody,
  //报文存档
  storedEventBodyList: [],
  selectedBodyId: '',
})
//代码块高度
const codemirrorHeight = ref(600)

window.jsonlint = jsonlint;
const cmOptions = reactive({
  mode: "application/json",
  lineNumbers: true,
  lineWiseCopyCut: true,
  gutters: ["CodeMirror-lint-markers"],
  lint: false, //是否检查格式
});

// 支持事件列表
const eventOptions = [
	{
	    value: 'deviceParamUpdate',
	    label: 'deviceParamUpdate'
	},
	{
	    value: 'exceptionRecord',
	    label: 'exceptionRecord'
	}
]

//格式化json
const formatJson = () => {
  try {
    // 1、JSON.parse：把JSON字符串转换为JSON对象
    // 2、JSON.stringify：把JSON对象 转换为 有缩进的 JSON字符串格式
    data.eventBody = JSON.stringify(JSON.parse(data.eventBody), null, '\t');
  } catch(error) {
	ElMessage.error('无效的JSON')
  }
}

//压缩
const compress = () => {
  data.eventBody = data.eventBody.replace(/[\r\n\t]/g, "")
}

//保存报文
const saveJson = ()=>{
	if (data.selectedBodyId == '') {
		// 新增
		ElMessageBox.prompt('请输入报文名称', '提示', {
		  confirmButtonText: '确认',
		  cancelButtonText: '取消'
		}).then(({ value }) => {
			let _id = getRandomString(6);
			data.storedEventBodyList.push({id: _id, name: value, content: data.eventBody})
			localStorage.setItem('eventBodyList', JSON.stringify(data.storedEventBodyList))
			data.selectedBodyId = _id
			ElMessage({
			  type: 'success',
			  message: `${value}保存成功`,
			})
		  })
		  .catch(() => {
		    ElMessage({
		      type: 'info',
		      message: '取消保存',
		    })
		})
	} else {
		// 编辑
		let editName = ''
		for(let i=0;i<data.storedEventBodyList.length;i++) {
			let _data = data.storedEventBodyList[i];
			if (_data.id == data.selectedBodyId) {
				_data.content = data.eventBody
				editName = _data.name
			}
		}

		if (editName != '') {
			ElMessageBox.confirm(
				'此操作将覆盖原报文，是否继续?',
				'确认',
				{
				  confirmButtonText: '是',
				  cancelButtonText: '取消',
				  type: 'warning',
				}
			).then(() => {
				  localStorage.setItem('eventBodyList', JSON.stringify(data.storedEventBodyList))
				  ElMessage({
				    type: 'success',
				    message: `${editName}保存成功`,
				  })
			})
		}
	}
}

//删除报文
const delEventBody = (id)=>{
	data.storedEventBodyList = data.storedEventBodyList.filter(item => item.id !== id);
	if (data.selectedBodyId == id) {
		data.selectedBodyId = ''
	}
	localStorage.setItem('eventBodyList', JSON.stringify(data.storedEventBodyList))
}

//选择报文
const selectEventBody = (item)=>{
	data.selectedBodyId = item.id
	data.eventBody = item.content
}

const newEventBody = ()=>{
	data.selectedBodyId = ''
	data.eventBody = defaultBody
}

//清理保存报文
const clearStoredBody = ()=>{
	data.selectedBodyId = ''
	data.storedEventBodyList = []
	localStorage.removeItem('eventBodyList')
}

// 计算代码块高度
const resizeCodeDiv = (height) => {
	codemirrorHeight.value = height
}

onMounted(() => {
	resizeCodeDiv()
   // 计算代码块高度
   const debouncedResize = debounce(resizeCodeDiv, 200);
   
   // 添加 resize 事件监听器
   //window.addEventListener('resize', debouncedResize);
   const codeDiv = document.getElementById("code-div");
   
   // 创建 ResizeObserver 实例
   const resizeObserver = new ResizeObserver(entries => {
	   for (let entry of entries) {
		   debouncedResize(entry.contentRect.height);
	   }
   });

   // 观察指定的 div
   resizeObserver.observe(codeDiv);
   
   //取出报文列表
   const _storedEventBodyList = localStorage.getItem('eventBodyList');
   data.storedEventBodyList = _storedEventBodyList ? JSON.parse(_storedEventBodyList) : [];
})
</script>

<style>
#code-div{
	flex:1;
	width:100%;
	position: relative;
	.code-content{
		position:absolute; 
		width:100%;
	}
}

.slide-body-container{
	position: relative;
	flex: 1;
	.slide-body-content{
		position:absolute; 
		width:100%;
		height: 100%;
	}
}
</style>